package com.rundow.common.sdk.listener;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.rundow.center.manager.service.BatchService;
import com.rundow.center.manager.service.DriverSdkService;
import com.rundow.center.manager.service.EventService;
import com.rundow.common.base.bean.driver.DriverConfiguration;
import com.rundow.common.base.bean.driver.DriverRegister;
import com.rundow.common.base.constant.CacheConstant;
import com.rundow.common.base.constant.CommonConstant;
import com.rundow.common.base.model.event.DriverEvent;
import com.rundow.common.base.model.event.DriverMetaEvent;
import com.rundow.common.sdk.service.EventSender;
import com.rundow.common.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.ThreadPoolExecutor;

@Slf4j
@Component
public class DriverEventListener {


    @Resource
    private RedisUtil redisUtil;
    @Resource
    private EventService eventService;
    @Resource
    private BatchService batchService;
    @Resource
    private DriverSdkService driverSdkService;

    @Resource
    private ThreadPoolExecutor threadPoolExecutor;

    @Resource
    private EventSender eventSender;

    @Async
    @EventListener
    public void driverEventReceive(DriverEvent driverEvent) {

        if (null == driverEvent || StrUtil.isEmpty(driverEvent.getDriverName())) {
            log.error("Invalid driver event {}", driverEvent);
            return;
        }
        log.debug("Driver {} event, From: {}, Received: {}", driverEvent.getType(), driverEvent.getDriverName(), driverEvent);
//            String routingKey = CommonConstant.Rabbit.ROUTING_DRIVER_METADATA_PREFIX + driverEvent.getServiceName();
        final String driverName = driverEvent.getDriverName();
        switch (driverEvent.getType()) {
            case CommonConstant.Driver.Event.DRIVER_HANDSHAKE:
                DriverConfiguration driverConfiguration = new DriverConfiguration(
                        CommonConstant.Driver.Type.DRIVER,
                        CommonConstant.Driver.Event.DRIVER_HANDSHAKE_BACK,
                        null,
                        CommonConstant.Response.OK
                );

                DriverMetaEvent handShakeDriverMetaEvent = new DriverMetaEvent(this, driverName, driverConfiguration);
                eventSender.sendSpringEvent(handShakeDriverMetaEvent);
                break;
            case CommonConstant.Driver.Event.DRIVER_REGISTER:
                driverConfiguration = new DriverConfiguration(
                        CommonConstant.Driver.Type.DRIVER,
                        CommonConstant.Driver.Event.DRIVER_REGISTER_BACK,
                        null,
                        CommonConstant.Response.OK
                );
                try {
                    driverSdkService.driverRegister(Convert.convert(DriverRegister.class, driverEvent.getContent()));
                } catch (Exception e) {
                    driverConfiguration.setResponse(e.getMessage());
                }

                DriverMetaEvent registerDriverMetaEvent = new DriverMetaEvent(this, driverName, driverConfiguration);
                eventSender.sendSpringEvent(registerDriverMetaEvent);
                break;
            case CommonConstant.Driver.Event.DRIVER_METADATA_SYNC:
                driverConfiguration = new DriverConfiguration(
                        CommonConstant.Driver.Type.DRIVER,
                        CommonConstant.Driver.Event.DRIVER_METADATA_SYNC_BACK,
                        null,
                        CommonConstant.Response.OK
                );
                try {
                    driverConfiguration.setContent(batchService.batchDriverMetadata(driverEvent.getDriverName()));
                } catch (Exception e) {
                    driverConfiguration.setResponse(e.getMessage());
                }
//                    rabbitTemplate.convertAndSend(
//                            CommonConstant.Rabbit.TOPIC_EXCHANGE_METADATA,
//                            routingKey,
//                            driverConfiguration
//                    );
                DriverMetaEvent syncDriverMetaEvent = new DriverMetaEvent(this, driverName, driverConfiguration);
                eventSender.sendSpringEvent(syncDriverMetaEvent);
                break;
            case CommonConstant.Driver.Event.DRIVER_HEARTBEAT:
                redisUtil.setKey(
                        CacheConstant.Prefix.DRIVER_STATUS_KEY_PREFIX + driverEvent.getDriverName(),
                        driverEvent.getContent(),
                        driverEvent.getTimeOut(),
                        driverEvent.getTimeUnit()
                );
                break;
            case CommonConstant.Driver.Event.ERROR:
                //TODO 去重
                threadPoolExecutor.execute(() -> eventService.addDriverEvent(driverEvent));
            default:
                log.error("Invalid event type, {}", driverEvent.getType());
                break;
        }


    }
}
